package service

import (
	"errors"
	"fmt"
	"gin-chat-server/common"
	"gin-chat-server/dto"
	"gin-chat-server/models"
	"time"

	"gorm.io/gorm"
)

type ChatService struct {
	db *gorm.DB
}

func NewChatService() *ChatService {
	return &ChatService{
		db: common.GetDB(),
	}
}

// 聊天室相关方法

// 创建聊天室
func (s *ChatService) CreateRoom(req *dto.CreateRoomRequest, creatorID string) (*models.Room, error) {
	room := &models.Room{
		Name:        req.Name,
		Description: req.Description,
		Type:        req.Type,
		CreatorID:   creatorID,
	}

	err := s.db.Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(room).Error; err != nil {
			return err
		}

		// 创建者自动成为房间成员和所有者
		member := &models.RoomMember{
			RoomID:   room.ID,
			UserID:   creatorID,
			Role:     "owner",
			IsActive: true,
		}

		return tx.Create(member).Error
	})

	if err != nil {
		return nil, err
	}

	return room, nil
}

// 获取用户所在的聊天室列表
func (s *ChatService) GetUserRooms(userID string, page, pageSize int) ([]*dto.RoomResponse, int64, error) {
	var members []*models.RoomMember
	var total int64

	offset := (page - 1) * pageSize

	// 查询用户所在的房间
	err := s.db.Model(&models.RoomMember{}).
		Where("user_id = ? AND is_active = ?", userID, true).
		Count(&total).
		Error

	if err != nil {
		return nil, 0, err
	}

	err = s.db.Model(&models.RoomMember{}).
		Where("user_id = ? AND is_active = ?", userID, true).
		Preload("Room.Creator").
		Preload("Room.Messages", "created_at = (SELECT MAX(created_at) FROM chat_message WHERE room_id = chat_room.id)").
		Offset(offset).
		Limit(pageSize).
		Find(&members).
		Error

	if err != nil {
		return nil, 0, err
	}

	// 转换为DTO
	var roomResponses []*dto.RoomResponse
	for _, member := range members {
		roomResponse := s.convertRoomToDTO(&member.Room, userID)
		roomResponses = append(roomResponses, roomResponse)
	}

	return roomResponses, total, nil
}

// 获取聊天室详情
func (s *ChatService) GetRoomByID(roomID, userID string) (*dto.RoomResponse, error) {
	var room models.Room

	// 检查用户是否是房间成员
	var count int64
	if err := s.db.Model(&models.RoomMember{}).
		Where("room_id = ? AND user_id = ? AND is_active = ?", roomID, userID, true).
		Count(&count).Error; err != nil {
		return nil, err
	}

	if count == 0 {
		return nil, errors.New("user is not a member of this room")
	}

	err := s.db.Preload("Creator").
		Preload("Members", "is_active = ?", true).
		Preload("Members.User").
		Where("id = ?", roomID).
		First(&room).Error

	if err != nil {
		return nil, err
	}

	return s.convertRoomToDTO(&room, userID), nil
}

// 加入聊天室
func (s *ChatService) JoinRoom(roomID, userID string) error {
	// 检查房间是否存在
	var room models.Room
	if err := s.db.First(&room, "id = ?", roomID).Error; err != nil {
		return errors.New("room not found")
	}

	// 检查用户是否已经是成员
	var member models.RoomMember
	err := s.db.Where("room_id = ? AND user_id = ?", roomID, userID).First(&member).Error
	if err == nil {
		if member.IsActive {
			return errors.New("user is already a member of this room")
		}
		// 重新激活成员
		member.IsActive = true
		member.JoinedAt = time.Now()
		return s.db.Save(&member).Error
	}

	if !errors.Is(err, gorm.ErrRecordNotFound) {
		return err
	}

	// 创建新成员
	member = models.RoomMember{
		RoomID:   roomID,
		UserID:   userID,
		Role:     "member",
		IsActive: true,
		JoinedAt: time.Now(),
	}

	return s.db.Create(&member).Error
}

// 离开聊天室
func (s *ChatService) LeaveRoom(roomID, userID string) error {
	var member models.RoomMember
	err := s.db.Where("room_id = ? AND user_id = ? AND is_active = ?", roomID, userID, true).
		First(&member).Error

	if err != nil {
		return errors.New("user is not a member of this room")
	}

	// 如果是房主，需要转让权限
	if member.Role == "owner" {
		// 查找其他管理员或成员
		var newOwner models.RoomMember
		err := s.db.Where("room_id = ? AND user_id != ? AND is_active = ?", roomID, userID, true).
			Order("role DESC, joined_at ASC").
			First(&newOwner).Error

		if err != nil {
			return errors.New("cannot leave room: no other members to transfer ownership")
		}

		// 转让所有权
		newOwner.Role = "owner"
		if err := s.db.Save(&newOwner).Error; err != nil {
			return err
		}
	}

	// 设置成员为非活跃状态
	member.IsActive = false
	return s.db.Save(&member).Error
}

// 消息相关方法

// 发送消息
func (s *ChatService) SendMessage(roomID, userID string, req *dto.SendMessageRequest) (*models.Message, error) {
	// 检查用户是否是房间成员
	var count int64
	if err := s.db.Model(&models.RoomMember{}).
		Where("room_id = ? AND user_id = ? AND is_active = ?", roomID, userID, true).
		Count(&count).Error; err != nil {
		return nil, err
	}

	if count == 0 {
		return nil, errors.New("user is not a member of this room")
	}

	message := &models.Message{
		RoomID:    roomID,
		UserID:    userID,
		Content:   req.Content,
		Type:      req.Type,
		Status:    "sent",
		CreatedAt: time.Now(),
	}

	// 处理文件消息
	if req.Type == "file" {
		if req.FileURL == "" {
			return nil, errors.New("file URL is required for file messages")
		}
		message.FileURL = &req.FileURL
		message.FileName = &req.FileName
		message.FileSize = &req.FileSize
	}

	// 处理回复消息
	if req.ReplyTo != "" {
		message.ReplyTo = &req.ReplyTo
	}

	err := s.db.Create(message).Error
	if err != nil {
		return nil, err
	}

	return message, nil
}

// 获取聊天室消息列表
func (s *ChatService) GetRoomMessages(roomID, userID string, page, pageSize int, before string) ([]*dto.MessageResponse, int64, error) {
	// 检查用户是否是房间成员
	var count int64
	if err := s.db.Model(&models.RoomMember{}).
		Where("room_id = ? AND user_id = ? AND is_active = ?", roomID, userID, true).
		Count(&count).Error; err != nil {
		return nil, 0, err
	}

	if count == 0 {
		return nil, 0, errors.New("user is not a member of this room")
	}

	var messages []*models.Message
	var total int64

	query := s.db.Model(&models.Message{}).Where("room_id = ?", roomID)

	if before != "" {
		query = query.Where("created_at < ?", before)
	}

	// 获取总数
	err := query.Count(&total).Error
	if err != nil {
		return nil, 0, err
	}

	// 获取消息列表
	offset := (page - 1) * pageSize
	err = query.Preload("User").
		Preload("Reply").
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&messages).Error

	if err != nil {
		return nil, 0, err
	}

	// 转换为DTO
	var messageResponses []*dto.MessageResponse
	for _, message := range messages {
		messageResponse := s.convertMessageToDTO(message, userID)
		messageResponses = append(messageResponses, messageResponse)
	}

	return messageResponses, total, nil
}

// 标记消息为已读
func (s *ChatService) MarkMessageAsRead(messageID, userID string) error {
	// 检查消息是否存在
	var message models.Message
	if err := s.db.First(&message, "id = ?", messageID).Error; err != nil {
		return errors.New("message not found")
	}

	// 检查用户是否是房间成员
	var count int64
	if err := s.db.Model(&models.RoomMember{}).
		Where("room_id = ? AND user_id = ? AND is_active = ?", message.RoomID, userID, true).
		Count(&count).Error; err != nil {
		return err
	}

	if count == 0 {
		return errors.New("user is not a member of this room")
	}

	// 检查是否已经标记为已读
	var readCount int64
	if err := s.db.Model(&models.MessageRead{}).
		Where("message_id = ? AND user_id = ?", messageID, userID).
		Count(&readCount).Error; err != nil {
		return err
	}

	if readCount > 0 {
		return nil // 已经标记为已读
	}

	// 创建已读记录
	read := &models.MessageRead{
		MessageID: messageID,
		UserID:    userID,
		ReadAt:    time.Now(),
	}

	return s.db.Create(read).Error
}

// 好友相关方法

// 发送好友请求
func (s *ChatService) SendFriendRequest(senderID, receiverID, message string) (*models.FriendRequest, error) {
	// 检查是否已经是好友
	var friend models.Friend
	err := s.db.Where("(user_id = ? AND friend_id = ?) OR (user_id = ? AND friend_id = ?)",
		senderID, receiverID, receiverID, senderID).
		First(&friend).Error

	if err == nil && friend.Status == "accepted" {
		return nil, errors.New("users are already friends")
	}

	// 检查是否已经发送过请求
	var existingRequest models.FriendRequest
	err = s.db.Where("(sender_id = ? AND receiver_id = ?) OR (sender_id = ? AND receiver_id = ?)",
		senderID, receiverID, receiverID, senderID).
		Where("status = ?", "pending").
		First(&existingRequest).Error

	if err == nil {
		return nil, errors.New("friend request already exists")
	}

	request := &models.FriendRequest{
		SenderID:   senderID,
		ReceiverID: receiverID,
		Message:    message,
		Status:     "pending",
		CreatedAt:  time.Now(),
	}

	err = s.db.Create(request).Error
	if err != nil {
		return nil, err
	}

	return request, nil
}

// 响应好友请求
func (s *ChatService) RespondFriendRequest(requestID, userID, status string) error {
	var request models.FriendRequest
	err := s.db.Where("id = ? AND receiver_id = ? AND status = ?", requestID, userID, "pending").
		First(&request).Error

	if err != nil {
		return errors.New("friend request not found or already processed")
	}

	// 更新请求状态
	request.Status = status
	request.UpdatedAt = time.Now()

	err = s.db.Save(&request).Error
	if err != nil {
		return err
	}

	// 如果接受请求，创建好友关系
	if status == "accepted" {
		friend1 := &models.Friend{
			UserID:    request.SenderID,
			FriendID:  request.ReceiverID,
			Status:    "accepted",
			CreatedAt: time.Now(),
		}

		friend2 := &models.Friend{
			UserID:    request.ReceiverID,
			FriendID:  request.SenderID,
			Status:    "accepted",
			CreatedAt: time.Now(),
		}

		err = s.db.Transaction(func(tx *gorm.DB) error {
			if err := tx.Create(friend1).Error; err != nil {
				return err
			}
			return tx.Create(friend2).Error
		})

		if err != nil {
			return err
		}

		// 创建私聊房间
		room := &models.Room{
			Name:      fmt.Sprintf("%s 和 %s 的聊天", request.SenderID, request.ReceiverID),
			Type:      "private",
			CreatorID: request.SenderID,
		}

		err = s.db.Transaction(func(tx *gorm.DB) error {
			if err := tx.Create(room).Error; err != nil {
				return err
			}

			// 添加双方为房间成员
			member1 := &models.RoomMember{
				RoomID:   room.ID,
				UserID:   request.SenderID,
				Role:     "owner",
				IsActive: true,
			}

			member2 := &models.RoomMember{
				RoomID:   room.ID,
				UserID:   request.ReceiverID,
				Role:     "member",
				IsActive: true,
			}

			if err := tx.Create(member1).Error; err != nil {
				return err
			}
			return tx.Create(member2).Error
		})

		if err != nil {
			return err
		}
	}

	return nil
}

// 获取好友列表
func (s *ChatService) GetFriends(userID string, page, pageSize int) ([]*dto.FriendResponse, int64, error) {
	var friends []*models.Friend
	var total int64

	offset := (page - 1) * pageSize

	err := s.db.Model(&models.Friend{}).
		Where("user_id = ? AND status = ?", userID, "accepted").
		Count(&total).
		Error

	if err != nil {
		return nil, 0, err
	}

	err = s.db.Where("user_id = ? AND status = ?", userID, "accepted").
		Preload("Friend").
		Offset(offset).
		Limit(pageSize).
		Find(&friends).
		Error

	if err != nil {
		return nil, 0, err
	}

	// 转换为DTO
	var friendResponses []*dto.FriendResponse
	for _, friend := range friends {
		friendResponse := s.convertFriendToDTO(friend)
		friendResponses = append(friendResponses, friendResponse)
	}

	return friendResponses, total, nil
}

// 获取好友请求列表
func (s *ChatService) GetFriendRequests(userID string, page, pageSize int) ([]*dto.FriendRequestResponse, int64, error) {
	var requests []*models.FriendRequest
	var total int64

	offset := (page - 1) * pageSize

	err := s.db.Model(&models.FriendRequest{}).
		Where("receiver_id = ? AND status = ?", userID, "pending").
		Count(&total).
		Error

	if err != nil {
		return nil, 0, err
	}

	err = s.db.Where("receiver_id = ? AND status = ?", userID, "pending").
		Preload("Sender").
		Preload("Receiver").
		Offset(offset).
		Limit(pageSize).
		Find(&requests).
		Error

	if err != nil {
		return nil, 0, err
	}

	// 转换为DTO
	var requestResponses []*dto.FriendRequestResponse
	for _, request := range requests {
		requestResponse := s.convertFriendRequestToDTO(request)
		requestResponses = append(requestResponses, requestResponse)
	}

	return requestResponses, total, nil
}

// 辅助方法：转换Room为DTO
func (s *ChatService) convertRoomToDTO(room *models.Room, userID string) *dto.RoomResponse {
	response := &dto.RoomResponse{
		ID:          room.ID,
		Name:        room.Name,
		Description: room.Description,
		Type:        room.Type,
		Avatar:      room.Avatar,
		CreatorID:   room.CreatorID,
		CreatedAt:   room.CreatedAt,
		UpdatedAt:   room.UpdatedAt,
	}

	// 设置创建者信息
	if room.Creator.ID != "" {
		response.Creator = &dto.UserResponse{
			ID:       room.Creator.ID,
			Username: room.Creator.Username,
			Nickname: room.Creator.Nickname,
			Avatar:   room.Creator.Avatar,
			Email:    room.Creator.Email,
		}
	}

	// 计算成员数量
	s.db.Model(&models.RoomMember{}).
		Where("room_id = ? AND is_active = ?", room.ID, true).
		Count(&response.MemberCount)

	// 获取最后一条消息
	var lastMessage models.Message
	err := s.db.Where("room_id = ?", room.ID).
		Order("created_at DESC").
		First(&lastMessage).Error

	if err == nil {
		response.LastMessage = s.convertMessageToDTO(&lastMessage, userID)
	}

	// 计算未读消息数量
	s.db.Model(&models.Message{}).
		Where("room_id = ? AND created_at > ?", room.ID,
			s.db.Model(&models.MessageRead{}).
				Where("message_id IN (SELECT id FROM chat_message WHERE room_id = ?) AND user_id = ?", room.ID, userID).
				Select("COALESCE(MAX(read_at), '1970-01-01')")).
		Count(&response.UnreadCount)

	return response
}

// 辅助方法：转换Message为DTO
func (s *ChatService) convertMessageToDTO(message *models.Message, userID string) *dto.MessageResponse {
	response := &dto.MessageResponse{
		ID:        message.ID,
		RoomID:    message.RoomID,
		UserID:    message.UserID,
		Content:   message.Content,
		Type:      message.Type,
		Status:    message.Status,
		ReplyTo:   message.ReplyTo,
		FileURL:   message.FileURL,
		FileName:  message.FileName,
		FileSize:  message.FileSize,
		CreatedAt: message.CreatedAt,
		UpdatedAt: message.UpdatedAt,
	}

	// 设置用户信息
	if message.User.ID != "" {
		response.User = &dto.UserResponse{
			ID:       message.User.ID,
			Username: message.User.Username,
			Nickname: message.User.Nickname,
			Avatar:   message.User.Avatar,
			Email:    message.User.Email,
		}
	}

	// 设置回复消息
	if message.Reply != nil {
		response.Reply = s.convertMessageToDTO(message.Reply, userID)
	}

	// 计算已读数量
	s.db.Model(&models.MessageRead{}).
		Where("message_id = ?", message.ID).
		Count(&response.ReadCount)

	// 检查当前用户是否已读
	var readCount int64
	s.db.Model(&models.MessageRead{}).
		Where("message_id = ? AND user_id = ?", message.ID, userID).
		Count(&readCount)
	response.IsRead = readCount > 0

	return response
}

// 辅助方法：转换Friend为DTO
func (s *ChatService) convertFriendToDTO(friend *models.Friend) *dto.FriendResponse {
	response := &dto.FriendResponse{
		ID:        friend.ID,
		UserID:    friend.UserID,
		FriendID:  friend.FriendID,
		Status:    friend.Status,
		CreatedAt: friend.CreatedAt,
		UpdatedAt: friend.UpdatedAt,
	}

	// 设置好友信息
	if friend.Friend.ID != "" {
		response.Friend = &dto.UserResponse{
			ID:       friend.Friend.ID,
			Username: friend.Friend.Username,
			Nickname: friend.Friend.Nickname,
			Avatar:   friend.Friend.Avatar,
			Email:    friend.Friend.Email,
		}
	}

	return response
}

// 辅助方法：转换FriendRequest为DTO
func (s *ChatService) convertFriendRequestToDTO(request *models.FriendRequest) *dto.FriendRequestResponse {
	response := &dto.FriendRequestResponse{
		ID:         request.ID,
		SenderID:   request.SenderID,
		ReceiverID: request.ReceiverID,
		Status:     request.Status,
		Message:    request.Message,
		CreatedAt:  request.CreatedAt,
		UpdatedAt:  request.UpdatedAt,
	}

	// 设置发送者信息
	if request.Sender.ID != "" {
		response.Sender = &dto.UserResponse{
			ID:       request.Sender.ID,
			Username: request.Sender.Username,
			Nickname: request.Sender.Nickname,
			Avatar:   request.Sender.Avatar,
			Email:    request.Sender.Email,
		}
	}

	// 设置接收者信息
	if request.Receiver.ID != "" {
		response.Receiver = &dto.UserResponse{
			ID:       request.Receiver.ID,
			Username: request.Receiver.Username,
			Nickname: request.Receiver.Nickname,
			Avatar:   request.Receiver.Avatar,
			Email:    request.Receiver.Email,
		}
	}

	return response
}
